package com.insight.modules.system.rule;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yuanqiao.insight.modules.CodeRuleSetting.entity.CodeRuleEnum;
import com.yuanqiao.insight.modules.CodeRuleSetting.entity.CodeRuleSetting;
import com.yuanqiao.insight.modules.CodeRuleSetting.service.ICodeRuleSettingService;
import org.apache.commons.lang3.StringUtils;
import com.insight.common.handler.IFillRuleHandler;
import com.insight.common.util.SpringContextUtils;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 填值规则Demo：生成订单号
 * 【测试示例】
 */
public class BizCodeGeneration implements IFillRuleHandler {

    /**
     * 生成编码规则的执行方法
     *
     * @param params   页面配置的固定参数（暂未用到）
     * @param formData 动态表单参数，必须包含：
     *                 - code-generation-bind: 绑定的编码规则code
     *                 - biz: 动态表单中的静态数据（JSON对象）
     *                 可选：
     *                 - index: 序号等辅助参数
     * @return 返回生成的编码字符串
     */
    @Override
    public Object execute(JSONObject params, JSONObject formData) {

        // 获取编码规则服务bean，用于查询和更新编码规则设置
        ICodeRuleSettingService iCodeRuleSettingService = SpringContextUtils.getBean(ICodeRuleSettingService.class);

        // 从前端表单参数中获取绑定的编码规则code
        String code = formData.getString("code-generation-bind");
        // 根据code查询数据库中对应的编码规则配置实体
        CodeRuleSetting codeRuleSetting = iCodeRuleSettingService.lambdaQuery().eq(CodeRuleSetting::getCode, code).one();
        // 获取编码规则配置中的规则集合（JSONArray格式）
        JSONArray rules = codeRuleSetting.getRules();

        // 如果没有配置规则，直接抛异常
        if (rules == null) {
            throw new IllegalStateException("没有编码规则");
        }

        StringBuilder stringBuilder = new StringBuilder(); // 用于拼接生成的编码字符串
        boolean update; // 标记是否成功更新编码规则的流水号等数据

        do {
            // 第二次及之后循环时，清空之前拼接的字符串
            stringBuilder.delete(0, stringBuilder.length());

            // 遍历所有规则，逐条处理
            for (JSONObject rule : rules.toJavaList(JSONObject.class)) {
                String type = rule.getString("type");     // 规则类型（code、date、serialNumber、dateNumber、biz）
                String content = rule.getString("content"); // 规则内容（字符串格式的具体内容或格式）

                if (CodeRuleEnum.code.toString().equals(type)) {
                    // 规则类型为固定编码，直接拼接内容
                    stringBuilder.append(content);

                } else if (CodeRuleEnum.date.toString().equals(type)) {
                    // 规则类型为日期，根据内容定义的格式格式化当前日期并拼接
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(content);
                    stringBuilder.append(simpleDateFormat.format(new Date()));

                } else if (CodeRuleEnum.serialNumber.toString().equals(type)) {
                    // 序列号规则，根据内容长度补0拼接流水号
                    // 例如content = "4"，流水号 1 格式化成 0001
                    stringBuilder.append(String.format("%0" + content + "d", codeRuleSetting.getBizSerialNumber()));
                    // 序列号自增
                    codeRuleSetting.setBizSerialNumber(codeRuleSetting.getBizSerialNumber() + 1);

                } else if (CodeRuleEnum.dateNumber.toString().equals(type)) {
                    // 日期序号规则，流水号按日期重置
                    // 先比较缓存中的bizDate和当前日期是否相同
                    if (codeRuleSetting.getBizDate().compareTo(getDate()) == 0) {
                        // 日期相同，流水号累加并拼接
                        stringBuilder.append(String.format("%0" + content + "d", codeRuleSetting.getBizDateNumber()));
                        codeRuleSetting.setBizDateNumber(codeRuleSetting.getBizDateNumber() + 1);
                    } else {
                        // 日期不相同，流水号重置为0并拼接，日期重置为当天
                        stringBuilder.append(String.format("%0" + content + "d", 0));
                        codeRuleSetting.setBizDateNumber(1);
                        codeRuleSetting.setBizDate(new Date());
                    }

                } else if (CodeRuleEnum.biz.toString().equals(type)) {
                    // 业务字段规则，从动态表单的biz字段中获取对应业务字段值拼接
                    JSONObject jsonObject = formData.getJSONObject("biz");
                    String biz = jsonObject.getString(content);

                    if (StringUtils.isNotBlank(biz)) {
                        // 业务字段有值，拼接
                        stringBuilder.append(biz);
                    } else {
                        // 业务字段无值，从biz.kfData中尝试获取
                        JSONObject kfData = jsonObject.getJSONObject("kfData");
                        String kfDataString = kfData.getString(content);
                        if (StringUtils.isNotBlank(kfDataString)) {
                            stringBuilder.append(kfDataString);
                        }
                    }
                }
            }
            // 更新数据库中的编码规则实体（流水号等变化），若失败则重新执行生成
            update = iCodeRuleSettingService.updateById(codeRuleSetting);

        } while (!update); // 直到更新成功为止，避免并发导致流水号未更新成功

        // 返回最终拼接生成的编码字符串
        return stringBuilder.toString();
    }

    /**
     * 获取当天零点日期
     * 计算逻辑：
     * 当前时间戳减去(当前时间戳+8小时偏移)%一天毫秒数，返回当天零点时间
     * @return 当天零点时间
     */
    private Date getDate() {
        Long createTime = new Date().getTime();
        // 28800000 = 8小时的毫秒数，86400000 = 一天毫秒数
        Long time = createTime - ((createTime + 28800000) % (86400000));
        return new Date(time);
    }
}

